home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / vm / vmServer.c < prev    next >
C/C++ Source or Header  |  1991-07-26  |  12KB  |  459 lines

  1. /* vmServer.c -
  2.  *
  3.  *         This file contains routines that read and write pages to/from the page
  4.  *    server and file server.
  5.  *
  6.  * Copyright (C) 1985 Regents of the University of California
  7.  * All rights reserved.
  8.  */
  9.  
  10. #ifndef lint
  11. static char rcsid[] = "$Header: /sprite/src/kernel/vm/RCS/vmServer.c,v 9.7 91/07/26 17:05:16 shirriff Exp $ SPRITE (Berkeley)";
  12. #endif not lint
  13.  
  14. #include <sprite.h>
  15. #include <vm.h>
  16. #include <vmInt.h>
  17. #include <vmSwapDir.h>
  18. #include <lock.h>
  19. #include <status.h>
  20. #include <sched.h>
  21. #include <sync.h>
  22. #include <dbg.h>
  23. #include <list.h>
  24. #include <string.h>
  25. #include <stdlib.h>
  26. #include <proc.h>
  27. #include <stdio.h>
  28.  
  29. Boolean    vmUseFSReadAhead = TRUE;
  30. extern    Boolean    vm_NoStickySegments;
  31. char        *sprintf();
  32.  
  33. /*
  34.  * Condition to wait on when want to do a swap file operation but someone
  35.  * is already doing one.  This is used for synchronization of opening
  36.  * of swap files.  It is possible that the open of the swap file could
  37.  * happen more than once if the open is not synchronized.
  38.  */
  39. Sync_Condition    swapFileCondition;
  40.  
  41. void    Fscache_BlocksUnneeded();
  42.  
  43.  
  44. /*
  45.  *----------------------------------------------------------------------
  46.  *
  47.  * VmSwapFileLock --
  48.  *
  49.  *    Set a lock on the swap file for the given segment.  If the lock
  50.  *    is already set then wait.
  51.  *
  52.  * Results:
  53.  *    None.
  54.  *
  55.  * Side effects:
  56.  *    Flags field in segment table entry is modified to make the segment
  57.  *    locked.
  58.  *----------------------------------------------------------------------
  59.  */
  60.  
  61. ENTRY void
  62. VmSwapFileLock(segPtr)
  63.     register    Vm_Segment    *segPtr;
  64. {
  65.     LOCK_MONITOR;
  66.  
  67.     while (segPtr->flags & VM_SWAP_FILE_LOCKED) {
  68.     (void) Sync_Wait(&swapFileCondition, FALSE);
  69.     }
  70.     segPtr->flags |= VM_SWAP_FILE_LOCKED;
  71.  
  72.     UNLOCK_MONITOR;
  73. }
  74.  
  75.  
  76. /*
  77.  *----------------------------------------------------------------------
  78.  *
  79.  * VmSwapFileUnlock --
  80.  *
  81.  *    Clear the lock on the swap file for the given segment.
  82.  *
  83.  * Results:
  84.  *    None.
  85.  *
  86.  * Side effects:
  87.  *    Flags field in segment table entry is modified to make the segment
  88.  *    unlocked and anyone waiting for the segment is awakened.
  89.  *----------------------------------------------------------------------
  90.  */
  91.  
  92. ENTRY void
  93. VmSwapFileUnlock(segPtr)
  94.     register    Vm_Segment    *segPtr;
  95. {
  96.     LOCK_MONITOR;
  97.  
  98.     segPtr->flags &= ~VM_SWAP_FILE_LOCKED;
  99.     Sync_Broadcast(&swapFileCondition);
  100.  
  101.     UNLOCK_MONITOR;
  102. }
  103.  
  104. /*
  105.  *----------------------------------------------------------------------
  106.  *
  107.  * VmPageServerRead --
  108.  *
  109.  *    Read the given page from the swap file into the given page frame.
  110.  *    This routine will panic if the swap file does not exist.
  111.  *
  112.  *    NOTE: It is assumed that the page frame that is to be written into
  113.  *          cannot be given to another segment.
  114.  *
  115.  * Results:
  116.  *    SUCCESS if the page server could be read from or an error if either
  117.  *    a swap file could not be opened or the page server could not be
  118.  *    read from the swap file.
  119.  *
  120.  * Side effects:
  121.  *    The hardware page is written into.
  122.  *
  123.  *----------------------------------------------------------------------
  124.  */
  125. ReturnStatus
  126. VmPageServerRead(virtAddrPtr, pageFrame)
  127.     Vm_VirtAddr            *virtAddrPtr;
  128.     unsigned    int        pageFrame;
  129. {
  130.     register    int        mappedAddr;
  131.     register    Vm_Segment    *segPtr;
  132.     int                status;
  133.     int                pageToRead;
  134.  
  135.     segPtr = virtAddrPtr->segPtr;
  136.     if (!(segPtr->flags & VM_SWAP_FILE_OPENED)) {
  137.     panic("VmPageServerRead: Trying to read from non-existent swap file.\n");
  138.     }
  139.  
  140.     if (segPtr->type == VM_STACK) {
  141.     pageToRead = mach_LastUserStackPage - virtAddrPtr->page;
  142.     } else if (segPtr->type == VM_SHARED) {
  143.     pageToRead= virtAddrPtr->page - segOffset(virtAddrPtr) +
  144.         (virtAddrPtr->sharedPtr->fileAddr>>vmPageShift);
  145.     } else {
  146.     pageToRead = virtAddrPtr->page - segPtr->offset;
  147.     }
  148.  
  149.     /*
  150.      * Map the page into the kernel's address space and fill it from the
  151.      * file server.
  152.      */
  153.     mappedAddr = (int) VmMapPage(pageFrame);
  154.     status = Fs_PageRead(segPtr->swapFilePtr, (Address) mappedAddr,
  155.              pageToRead << vmPageShift, vm_PageSize, FS_SWAP_PAGE);
  156.     VmUnmapPage((Address) mappedAddr);
  157.  
  158.     return(status);
  159. }
  160.  
  161.  
  162.  
  163. /*
  164.  *----------------------------------------------------------------------
  165.  *
  166.  * VmPageServerWrite --
  167.  *
  168.  *    Write the given page frame to the swap file.  If the swap file is
  169.  *    not open yet then it will be open.
  170.  *
  171.  *    NOTE: It is assumed that the page frame that is to be read from
  172.  *          cannot be given to another segment.
  173.  *
  174.  * Results:
  175.  *    SUCCESS if the page server could be written to or an error if either
  176.  *    a swap file could not be opened or the page server could not be
  177.  *    written to.
  178.  *
  179.  * Side effects:
  180.  *    If no swap file exists, then one is created.
  181.  *
  182.  *----------------------------------------------------------------------
  183.  */
  184. ReturnStatus
  185. VmPageServerWrite(virtAddrPtr, pageFrame, toDisk)
  186.     Vm_VirtAddr        *virtAddrPtr;
  187.     unsigned int    pageFrame;
  188.     Boolean        toDisk;
  189. {
  190.     register    int        mappedAddr;
  191.     register    Vm_Segment    *segPtr;
  192.     ReturnStatus        status;
  193.     int                pageToWrite;
  194.  
  195.     vmStat.pagesWritten++;
  196.  
  197.     segPtr = virtAddrPtr->segPtr;
  198.  
  199.     /*
  200.      * Lock the swap file while opening it so that we don't have more than
  201.      * one swap file open at a time.
  202.      */
  203.     VmSwapFileLock(segPtr);
  204.     if (!(segPtr->flags & VM_SWAP_FILE_OPENED)) {
  205.     status = VmOpenSwapFile(segPtr);
  206.     if (status != SUCCESS) {
  207.         VmSwapFileUnlock(segPtr);
  208.         return(status);
  209.     }
  210.     }
  211.     VmSwapFileUnlock(segPtr);
  212.  
  213.     if (segPtr->type == VM_STACK) {
  214.     pageToWrite = mach_LastUserStackPage - virtAddrPtr->page;
  215.     } else {
  216.     pageToWrite = virtAddrPtr->page - segOffset(virtAddrPtr);
  217.     }
  218.  
  219.     /*
  220.      * Map the page into the kernel's address space and write it out.
  221.      */
  222.     VmMach_FlushPage(virtAddrPtr, FALSE);
  223.     mappedAddr = (int) VmMapPage(pageFrame);
  224.     status = Fs_PageWrite(segPtr->swapFilePtr, (Address) mappedAddr,
  225.               pageToWrite << vmPageShift, vm_PageSize, toDisk);
  226.     VmUnmapPage((Address) mappedAddr);
  227.  
  228.     return(status);
  229. }
  230.  
  231.  
  232. /*
  233.  *----------------------------------------------------------------------
  234.  *
  235.  * VmCopySwapSpace --
  236.  *
  237.  *    Copy the swap space for all pages that have been written out to swap
  238.  *    space for the source segment into the destination segments swap space.
  239.  *
  240.  * Results:
  241.  *    Error if swap file could not be opened, read or written.  Otherwise
  242.  *    SUCCESS is returned.
  243.  *
  244.  * Side effects:
  245.  *    None.
  246.  *
  247.  *----------------------------------------------------------------------
  248.  */
  249.  
  250. ReturnStatus
  251. VmCopySwapSpace(srcSegPtr, destSegPtr)
  252.     register    Vm_Segment    *srcSegPtr;
  253.     register    Vm_Segment    *destSegPtr;
  254. {
  255.     register    int    page;
  256.     register    Vm_PTE    *ptePtr;
  257.     ReturnStatus    status = SUCCESS;
  258.     register    int    i;
  259.  
  260.     VmSwapFileLock(srcSegPtr);
  261.     if (!(srcSegPtr->flags & VM_SWAP_FILE_OPENED)) {
  262.     VmSwapFileUnlock(srcSegPtr);
  263.     return(SUCCESS);
  264.     }
  265.     VmSwapFileUnlock(srcSegPtr);
  266.  
  267.     VmSwapFileLock(destSegPtr);
  268.     if (!(destSegPtr->flags & VM_SWAP_FILE_OPENED)) {
  269.     status = VmOpenSwapFile(destSegPtr);
  270.     if (status != SUCCESS) {
  271.         VmSwapFileUnlock(destSegPtr);
  272.         return(status);
  273.     }
  274.     }
  275.     VmSwapFileUnlock(destSegPtr);
  276.  
  277.     if (destSegPtr->type == VM_STACK) {
  278.     page = destSegPtr->numPages - 1;
  279.     ptePtr = VmGetPTEPtr(destSegPtr, mach_LastUserStackPage - 
  280.                              destSegPtr->numPages + 1);
  281.     } else {
  282.     page = 0;
  283.         ptePtr = destSegPtr->ptPtr;
  284.     }
  285.  
  286.     for (i = 0; i < destSegPtr->numPages; i++, VmIncPTEPtr(ptePtr, 1)) {
  287.  
  288.     if (*ptePtr & VM_IN_PROGRESS_BIT) {
  289.         *ptePtr &= ~VM_IN_PROGRESS_BIT;
  290.         /*
  291.          * The page is on the swap file and not in memory.  Need to copy
  292.          * the page in the file.
  293.          */
  294.         vmStat.swapPagesCopied++;
  295.         status = Fs_PageCopy(srcSegPtr->swapFilePtr, 
  296.                 destSegPtr->swapFilePtr, 
  297.                 page << vmPageShift, vm_PageSize);
  298.         if (status != SUCCESS) {
  299.         break;
  300.         }
  301.     }
  302.     if (destSegPtr->type == VM_STACK) {
  303.         page--;
  304.     } else {
  305.         page++;
  306.     }
  307.     }
  308.  
  309.     return(status);
  310. }
  311.  
  312.  
  313. /*
  314.  *----------------------------------------------------------------------
  315.  *
  316.  * VmFileServerRead --
  317.  *
  318.  *    Read the given page from the file server into the given page frame.
  319.  *
  320.  *    NOTE: It is assumed that the page frame that is to be written into
  321.  *          cannot be given to another segment.
  322.  *
  323.  * Results:
  324.  *    Error if file server could not be read from, SUCCESS otherwise.
  325.  *
  326.  * Side effects:
  327.  *    The hardware page is written into.
  328.  *
  329.  *----------------------------------------------------------------------
  330.  */
  331.  
  332. ReturnStatus
  333. VmFileServerRead(virtAddrPtr, pageFrame)
  334.     Vm_VirtAddr        *virtAddrPtr;
  335.     unsigned int    pageFrame;
  336. {
  337.     register    int        mappedAddr;
  338.     register    Vm_Segment    *segPtr;
  339.     int                length;
  340.     int                status;
  341.     int                offset;
  342.  
  343.     segPtr = virtAddrPtr->segPtr;
  344.  
  345.     /*
  346.      * Map the page frame into the kernel's address space.
  347.      */
  348.     mappedAddr = (int) VmMapPage(pageFrame);
  349.     /*
  350.      * The address to read is just the page offset into the segment
  351.      * ((page - offset) << vmPageShift) plus the offset of this segment into
  352.      * the file (fileAddr).
  353.      * (We have to use the right offset for shared memory.
  354.      */
  355.     length = vm_PageSize;
  356.     if (segPtr->type == VM_SHARED) {
  357.     if (virtAddrPtr->sharedPtr == (Vm_SegProcList *)NIL) {
  358.         printf("*** NIL sharedPtr in VmFileServerRead\n");
  359.         return FAILURE;
  360.     }
  361.     offset = ((virtAddrPtr->page - segOffset(virtAddrPtr)) << vmPageShift)
  362.         + virtAddrPtr->sharedPtr->fileAddr;
  363.     } else {
  364.     offset = ((virtAddrPtr->page - segOffset(virtAddrPtr)) << vmPageShift)
  365.         + segPtr->fileAddr;
  366.     }
  367.     if (vmPrefetch || !vmUseFSReadAhead) {
  368.     /*
  369.      * If we are using prefetch then do the reads ourselves.
  370.      */
  371.     if (segPtr->type == VM_CODE && !vm_NoStickySegments) {
  372.         status = Fs_PageRead(segPtr->filePtr, (Address)mappedAddr, offset,
  373.                  length, FS_CODE_PAGE);
  374.     } else {
  375.         status = Fs_PageRead(segPtr->filePtr, (Address)mappedAddr, offset,
  376.                  length, FS_HEAP_PAGE);
  377.     }
  378.     } else {
  379.     /*
  380.      * No prefetch so use the file system full blown mechanism so
  381.      * that we can take advantage of its read ahead.
  382.      */
  383.     status = Fs_Read(segPtr->filePtr, (Address) mappedAddr, offset,
  384.              &length);
  385.     if (status == SUCCESS && !vm_NoStickySegments && 
  386.         segPtr->type == VM_CODE) {
  387.         /*
  388.          * Tell the file system that we just read some file system blocks
  389.          * into virtual memory.
  390.          */
  391.         Fscache_BlocksUnneeded(segPtr->filePtr, offset, vm_PageSize, TRUE);
  392.     }
  393.     }
  394.     VmUnmapPage((Address) mappedAddr);
  395.     if (status != SUCCESS) {
  396.     printf("%s VmFileServerRead: Error %x from Fs_Read or Fs_PageRead\n",
  397.         "Warning:", status);
  398.     return(status);
  399.     }
  400.  
  401.     return(SUCCESS);
  402. }
  403.  
  404.  
  405.  
  406. /*
  407.  *----------------------------------------------------------------------
  408.  *
  409.  * VmCopySwapPage --
  410.  *
  411.  *    Copy the swap page from the source segment's swap file to the
  412.  *    destination.
  413.  *
  414.  * Results:
  415.  *    Error if swap file could not be opened, read or written.  Otherwise
  416.  *    SUCCESS is returned.
  417.  *
  418.  * Side effects:
  419.  *    None.
  420.  *
  421.  *----------------------------------------------------------------------
  422.  */
  423. ReturnStatus
  424. VmCopySwapPage(srcSegPtr, virtPage, destSegPtr)
  425.     register    Vm_Segment    *srcSegPtr;    /* Source for swap file. */
  426.     int                virtPage;    /* Virtual page to copy. */
  427.     register    Vm_Segment    *destSegPtr;    /* Destination swap file. */
  428. {
  429.     int            pageToCopy;
  430.     ReturnStatus    status;
  431.  
  432.     /*
  433.      * Lock the swap file while opening it so that we don't have more than
  434.      * one swap file open at a time.
  435.      */
  436.     VmSwapFileLock(destSegPtr);
  437.     if (!(destSegPtr->flags & VM_SWAP_FILE_OPENED)) {
  438.     status = VmOpenSwapFile(destSegPtr);
  439.     if (status != SUCCESS) {
  440.         VmSwapFileUnlock(destSegPtr);
  441.         return(status);
  442.     }
  443.     }
  444.     VmSwapFileUnlock(destSegPtr);
  445.  
  446.     vmStat.swapPagesCopied++;
  447.     if (destSegPtr->type == VM_STACK) {
  448.     pageToCopy = mach_LastUserStackPage - virtPage;
  449.     } else {
  450.     pageToCopy = virtPage - destSegPtr->offset;
  451.     }
  452.  
  453.     status = Fs_PageCopy(srcSegPtr->swapFilePtr, 
  454.              destSegPtr->swapFilePtr, 
  455.              pageToCopy << vmPageShift, vm_PageSize);
  456.  
  457.     return(status);
  458. }
  459.